//
//  Date+AG.swift
//  ASW
//
//  Created by zhuxuhong on 2020/12/19.
//

import UIKit
import SwifterSwift

public typealias DateComponentSet = Set<Calendar.Component>

extension Date {
    public enum TimeAgoComponent {
        case secondsAgo, minutesAgo, hoursAgo
        case weekDaysAgo, weeksAgo, monthsAgo, yearsAgo
        
        public enum Translate {
            case cn
            case en
            case individual(seconds: String, minutes: String, hours: String, days: String, weeks: String, months: String, years: String)
        }
        
        public func unitString(locale: Translate) -> String {
            switch locale {
            case .cn:
                switch self {
                case .secondsAgo: return "秒"
                case .minutesAgo: return "分钟"
                case .hoursAgo: return "小时"
                case .weekDaysAgo: return "天"
                case .weeksAgo: return "周"
                case .monthsAgo: return "个月"
                case .yearsAgo: return "年"
                }
            case .en:
                switch self {
                case .secondsAgo: return " seconds"
                case .minutesAgo: return " minutes"
                case .hoursAgo: return " hours"
                case .weekDaysAgo: return " days"
                case .weeksAgo: return " weeks"
                case .monthsAgo: return " months"
                case .yearsAgo: return " years"
                }
            case .individual(let seconds, let minutes, let hours, let  days, let weeks, let months, let years):
                switch self {
                case .secondsAgo: return seconds
                case .minutesAgo: return minutes
                case .hoursAgo: return hours
                case .weekDaysAgo: return days
                case .weeksAgo: return weeks
                case .monthsAgo: return months
                case .yearsAgo: return years
                }
            }
        }
        
        public func agoString(locale: Translate) -> String {
            switch locale {
            case .cn:
                return "前"
            case .en:
                return " ago"
            case .individual(let seconds, let minutes, let hours, let  days, let weeks, let months, let years):
                switch self {
                case .secondsAgo: return seconds
                case .minutesAgo: return minutes
                case .hoursAgo: return hours
                case .weekDaysAgo: return days
                case .weeksAgo: return weeks
                case .monthsAgo: return months
                case .yearsAgo: return years
                }
            }
        }
    }
    
    public func bw_toPassedTimesString(locale: TimeAgoComponent.Translate = .cn) -> String {
        let comp = bw_toPassedTimesComponent()
        return "\(comp.value)" + comp.component.unitString(locale: locale) + comp.component.agoString(locale: locale)
    }
    
    public func bw_toPassedTimesComponent() -> (component: TimeAgoComponent, value: Int) {
        let now = Date()
        if now.minutesSince(self) < 1 {
            return (component: TimeAgoComponent.secondsAgo, value: Int(now.secondsSince(self)))
        }
        else if now.hoursSince(self) < 1 {
            return (component: .minutesAgo, value: Int(now.minutesSince(self)))
        }
        else if now.daysSince(self) < 1 {
            return (component: .hoursAgo, value: Int(now.hoursSince(self)))
        }
        else if now.weeksSince(self) < 1 {
            return (component: .weekDaysAgo, value: Int(now.daysSince(self)))
        }
        else if now.monthsSince(self) < 1 {
            return (component: .weeksAgo, value: Int(now.weeksSince(self)))
        }
        else if now.yearsSince(self) < 1 {
            return (component: .monthsAgo, value: Int(now.monthsSince(self)))
        }
        return (component: .yearsAgo, value: Int(now.yearsSince(self)))
    }
}

extension Date {
    func yearsSince(_ date: Date) -> Double {
        return timeIntervalSince(date)/(3600*24*365)
    }
    func monthsSince(_ date: Date) -> Double {
        return timeIntervalSince(date)/(3600*24*31)
    }
    func weeksSince(_ date: Date) -> Double {
        return timeIntervalSince(date)/(3600*24*7)
    }
}

extension Date {
    public func bw_formattedDateString(
        components: Set<Calendar.Component>,
        joinTag: DateFormatter.DateJoinTag = .line1
    ) -> String {
        let oldFormat = DateFormatter.shared.dateFormat
        DateFormatter.shared.dateFormat = DateFormatter.bw_dateFormatString(components: components, joinTag: joinTag)
        let string = DateFormatter.shared.string(from: self)
        DateFormatter.shared.dateFormat = oldFormat
        return string
    }
    
    public func bw_formattedTimeString(
        components: Set<Calendar.Component>,
        joinTag: DateFormatter.TimeJoinTag = .colon
    ) -> String {
        let oldFormat = DateFormatter.shared.dateFormat
        DateFormatter.shared.dateFormat = DateFormatter.bw_timeFormatString(components: components, joinTag: joinTag)
        let string = DateFormatter.shared.string(from: self)
        DateFormatter.shared.dateFormat = oldFormat
        return string
    }
    
    public func bw_toString(
        components: DateComponentSet = .full,
        dateJoinTag: DateFormatter.DateJoinTag = .line1,
        timeJoinTag: DateFormatter.TimeJoinTag = .colon
    ) -> String {
        let date = bw_formattedDateString(components: components, joinTag: dateJoinTag)
        let time = bw_formattedTimeString(components: components, joinTag: timeJoinTag)
        return date + " " + time
    }
    
    public func bw_toSecondsString() -> String {
        return bw_toString(components: .fullToSeconds)
    }
    public func bw_toMinutesString() -> String {
        return bw_toString(components: .fullToMinutes)
    }
    public func bw_toDaysString() -> String {
        return bw_toString(components: .yearMonthDays)
    }
}
